﻿/*!
    \file    change log.txt
    \brief   change log for GD32H73x_75x demo

    \version 2026-07-31, V2.3.0, demo for GD32H73x_75x
*/

/*
    Copyright (c) 2026 GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/

******************* V2.3.0 2026-07-31 ************************************************************************************
______________________Common______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H73x_75x_Firmware_Library

fix reason:
update the version from V1.5.0 to V1.6.0

__________________________________________________________________________________________________________________________

______________________CAN_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/19_CAN_Network/main.c

fix reason:
Use the data buffer embedded in the CAN mailbox descriptor instead of
external tx/rx data arrays.

V2.2.0:
const uint8_t tx_data[BUFFER_SIZE] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8};
uint8_t rx_data[BUFFER_SIZE];

    /* tx message content */
    transmit_message.data = (uint32_t *)(tx_data);

    /* rx mailbox */
    receive_message.data = (uint32_t *)(rx_data);

        if(0U == memcmp(rx_data, tx_data, receive_message.data_bytes)) {
            printf("\r\nCAN1 receive data: \r\n");
            for(i = 0U; i < receive_message.data_bytes; i++) {
                printf("%02x ", rx_data[i]);
            }

V2.3.0:
none

    /* fill the data for CAN1 transmit */
    for(i = 0; i < BUFFER_SIZE; i++){
        transmit_message.data[i] = 0xA0 + i;
    }

        if(0U == memcmp(receive_message.data, transmit_message.data, receive_message.data_bytes)) {
            printf("\r\nCAN1 receive data: \r\n");
            for(i = 0U; i < receive_message.data_bytes; i++) {
                printf("%02x ", receive_message.data[i]);
            }

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/19_CAN_Network/main.c

fix reason:
Add MPU configuration function to prevent speculative prefetching of external
memory, which may cause CPU read locks and even system errors, and add USART
configuration for printf.

V2.2.0:
    /* enable the CPU cache */
    cache_enable();
    /* configure systick */
    systick_config();
    /*delay 1 seconds*/
    delay_1ms(1000);
    /* enable peripheral clock */
    rcu_config();
    /* configure GPIO */
    gpio_config();

V2.3.0:
    /* enable the CPU cache */
    cache_enable();
    mpu_config();
    /* configure systick */
    systick_config();
    /*delay 1 seconds*/
    delay_1ms(1000);
    /* enable peripheral clock */
    rcu_config();
    /* USART parameter configuration */
    gd_eval_com_init(EVAL_COM);
    /* configure GPIO */
    gpio_config();

void mpu_config(void)
{
    mpu_region_init_struct mpu_init_struct;
    mpu_region_struct_para_init(&mpu_init_struct);

    /* disable the MPU */
    ARM_MPU_Disable();
    ARM_MPU_SetRegion(0, 0);

    /* configure the MPU attributes for the entire 4GB area, Reserved, no access */
    /* This configuration is highly recommended to prevent Speculative Prefetching of external memory,
       which may cause CPU read locks and even system errors */
    mpu_init_struct.region_base_address  = 0x0;
    mpu_init_struct.region_size          = MPU_REGION_SIZE_4GB;
    mpu_init_struct.access_permission    = MPU_AP_NO_ACCESS;
    mpu_init_struct.access_bufferable    = MPU_ACCESS_NON_BUFFERABLE;
    mpu_init_struct.access_cacheable     = MPU_ACCESS_NON_CACHEABLE;
    mpu_init_struct.access_shareable     = MPU_ACCESS_SHAREABLE;
    mpu_init_struct.region_number        = MPU_REGION_NUMBER0;
    mpu_init_struct.subregion_disable    = 0x87;
    mpu_init_struct.instruction_exec     = MPU_INSTRUCTION_EXEC_NOT_PERMIT;
    mpu_init_struct.tex_type             = MPU_TEX_TYPE0;
    mpu_region_config(&mpu_init_struct);
    mpu_region_enable();

    /* enable the MPU */
    ARM_MPU_Enable(MPU_MODE_PRIV_DEFAULT);
}

__________________________________________________________________________________________________________________________

______________________DCI_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/25_DCI_OV2640/Soft_Drive/sccb.c

fix reason:
Add timeout mechanism to the I2C flag waiting loops in SCCB byte write/read
functions to avoid dead loops, and print error message on timeout.

V2.2.0:
    i2c_data_transmit(DCI_SCCB, reg);
    while(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_TI)) {
    }
    i2c_data_transmit(DCI_SCCB, data);
    while(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_TI)) {
    }
    while(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_STPDET)) {
    }
    i2c_flag_clear(DCI_SCCB, I2C_FLAG_STPDET);

V2.3.0:
    i2c_data_transmit(DCI_SCCB, reg);
    /* wait until transmission is complete or timeout */
    FW_WAIT_WHILE_TIMEOUT(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_TI), 300, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] I2C_FLAG_TI (reg) get timeout !!!\r\n", __FILE__, __LINE__);
        return 0xFF;
    }

    i2c_data_transmit(DCI_SCCB, data);
    /* wait until transmission is complete or timeout */
    FW_WAIT_WHILE_TIMEOUT(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_TI), 300, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] I2C_FLAG_TI (data) get timeout !!!\r\n", __FILE__, __LINE__);
        return 0xFF;
    }

    /* wait until stop condition is detected or timeout */
    FW_WAIT_WHILE_TIMEOUT(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_STPDET), 300, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] I2C_FLAG_STPDET get timeout !!!\r\n", __FILE__, __LINE__);
        return 0xFF;
    }
    i2c_flag_clear(DCI_SCCB, I2C_FLAG_STPDET);

V2.2.0:
    i2c_data_transmit(DCI_SCCB, reg);
    while(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_TI)) {
    }
    while(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_STPDET)) {
    }
    i2c_flag_clear(DCI_SCCB, I2C_FLAG_STPDET);

    while(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_RBNE)) {
    }
    *data = i2c_data_receive(DCI_SCCB);
    while(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_STPDET)) {
    }
    i2c_flag_clear(DCI_SCCB, I2C_FLAG_STPDET);

V2.3.0:
    i2c_data_transmit(DCI_SCCB, reg);
    /* wait until transmission is complete or timeout */
    FW_WAIT_WHILE_TIMEOUT(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_TI), 300, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] I2C_FLAG_TI (reg) get timeout !!!\r\n", __FILE__, __LINE__);
        return 0xFF;
    }

    /* wait until stop condition is detected or timeout */
    FW_WAIT_WHILE_TIMEOUT(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_STPDET), 300, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] I2C_FLAG_STPDET (write phase) get timeout !!!\r\n", __FILE__, __LINE__);
        return 0xFF;
    }
    i2c_flag_clear(DCI_SCCB, I2C_FLAG_STPDET);

    /* wait until data is available in receive buffer or timeout */
    FW_WAIT_WHILE_TIMEOUT(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_RBNE), 300, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] I2C_FLAG_RBNE get timeout !!!\r\n", __FILE__, __LINE__);
        return 0xFF;
    }
    *data = i2c_data_receive(DCI_SCCB);

    /* wait until stop condition is detected or timeout */
    FW_WAIT_WHILE_TIMEOUT(SET != i2c_flag_get(DCI_SCCB, I2C_FLAG_STPDET), 300, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] I2C_FLAG_STPDET (read phase) get timeout !!!\r\n", __FILE__, __LINE__);
        return 0xFF;
    }
    i2c_flag_clear(DCI_SCCB, I2C_FLAG_STPDET);

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/25_DCI_OV2640/main.c

fix reason:
Replace the dead loops with error message printing and return when PLL2
configuration fails or PLL2 clock is not stable.

V2.2.0:
    if(ERROR == rcu_pll2_config(25, 120, 3, 3, 3)) {
        while(1) {
        }
    }

    if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) {
        while(1) {
        }
    }

V2.3.0:
    if(ERROR == rcu_pll2_config(25, 120, 3, 3, 3)) {
        printf("[ERROR] [%s:%d] rcu_pll2_config failed !!!\r\n", __FILE__, __LINE__);
        return;
    }

    if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) {
        printf("[ERROR] [%s:%d] RCU_PLL2_CK stable timeout !!!\r\n", __FILE__, __LINE__);
        return;
    }

__________________________________________________________________________________________________________________________

______________________ENET________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/FreeRTOS_tcpudp/inc/lwipopts.h

fix reason:
Use lwIP private timeval definition for GD_ECLIPSE_GCC to fix the build issue.

V2.2.0:
#ifdef GD_ECLIPSE_GCC
#define LWIP_TIMEVAL_PRIVATE    0
#endif /* GD_ECLIPSE_GCC */

V2.3.0:
#ifdef GD_ECLIPSE_GCC
#define LWIP_TIMEVAL_PRIVATE    1
#endif /* GD_ECLIPSE_GCC */

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/FreeRTOS_tcpudp/inc/main.h
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_tcpudp/inc/main.h

fix reason:
Update the default board IP address and remote station IP address.

V2.2.0:
#define BOARD_IP_ADDR3   60

#define IP_S_ADDR3   158

V2.3.0:
#define BOARD_IP_ADDR3   39

#define IP_S_ADDR3   79

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/FreeRTOS_tcpudp/src/gd32h73x_75x_enet_eval.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_tcpudp/src/gd32h73x_75x_enet_eval.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_webserver/src/gd32h73x_75x_enet_eval.c

fix reason:
Replace the dead loops with error message printing when ENET initialization
fails or ENET software reset times out.

V2.2.0:
    if(0 == enet_init_status) {
        while(1) {
        }
    }

    /* reset enet by software */
    reval_state = enet_software_reset(enet_periph);
    if(ERROR == reval_state) {
        while(1) {}
    }

V2.3.0:
    if(0 == enet_init_status) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] ENET initialize failed !!!\r\n", __FILE__, __LINE__);
    }

    /* reset enet by software */
    reval_state = enet_software_reset(enet_periph);
    if(ERROR == reval_state) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] ENET software reset timeout !!!\r\n", __FILE__, __LINE__);
    }

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/FreeRTOS_tcpudp/src/gd32h73x_75x_enet_ext.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_tcpudp/src/gd32h73x_75x_enet_ext.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_webserver/src/gd32h73x_75x_enet_ext.c

fix reason:
Adjust the ENET1 DMA descriptor and buffer addresses to avoid overlapping
with the ENET0 buffers.

V2.2.0:
__attribute__((section(".ARM.__at_0x30000000")))  volatile enet_descriptors_struct  rxdesc_tab1[ENET_RXBUF_NUM];        /*!< ENET1 RxDMA descriptor */
__attribute__((section(".ARM.__at_0x30000160")))  volatile enet_descriptors_struct  txdesc_tab1[ENET_TXBUF_NUM];        /*!< ENET1 TxDMA descriptor */
__attribute__((section(".ARM.__at_0x30000300")))  volatile uint8_t rx_buff1[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];           /*!< ENET1 receive buffer */
__attribute__((section(".ARM.__at_0x30002100")))  volatile uint8_t tx_buff1[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];           /*!< ENET1 transmit buffer */

V2.3.0:
__attribute__((section(".ARM.__at_0x30004000")))  volatile enet_descriptors_struct  rxdesc_tab1[ENET_RXBUF_NUM];        /*!< ENET1 RxDMA descriptor */
__attribute__((section(".ARM.__at_0x30004160")))  volatile enet_descriptors_struct  txdesc_tab1[ENET_TXBUF_NUM];        /*!< ENET1 TxDMA descriptor */
__attribute__((section(".ARM.__at_0x30004300")))  volatile uint8_t rx_buff1[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];           /*!< ENET1 receive buffer */
__attribute__((section(".ARM.__at_0x30006100")))  volatile uint8_t tx_buff1[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];           /*!< ENET1 transmit buffer */

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_tcpudp/src/gd32h73x_75x_it.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_webserver/src/gd32h73x_75x_it.c

fix reason:
Delete the redundant tick_increment and the duplicated time_update function
call in the SysTick handler.

V2.2.0:
    /* update the g_localtime by adding SYSTEMTICK_PERIOD_MS each SysTick interrupt */
    time_update();
    tick_increment();
}

    /* update the g_localtime by adding SYSTEMTICK_PERIOD_MS each SysTick interrupt */
    time_update();

V2.3.0:
    /* update the g_localtime by adding SYSTEMTICK_PERIOD_MS each SysTick interrupt */
    time_update();
}

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_webserver/src/fsdata.c

fix reason:
Update the web page data of the raw webserver demo.

V2.2.0:
none

V2.3.0:
Updated the fsdata.c web page data

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/FreeRTOS_tcpudp/inc/lwipopts.h
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_tcpudp/inc/lwipopts.h
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_webserver/inc/lwipopts.h

fix reason:
Delete the LwIP RAM heap pointer relocation macro to prevent address conflicts.

V2.2.0:
/* Relocate the LwIP RAM heap pointer */
#define LWIP_RAM_HEAP_POINTER    (0x30004000)

V2.3.0:
none

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/FreeRTOS_tcpudp/src/gd32h73x_75x_enet_ext.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_tcpudp/src/gd32h73x_75x_enet_ext.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/26_ENET/Projects/Raw_webserver/src/gd32h73x_75x_enet_ext.c

fix reason:
Match the ENET DMA descriptor size macro name modification in the firmware library.

V2.2.0:
dma_current_rxdesc0 = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc0 + ENET_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL(
                      enet_periph))));

V2.3.0:
dma_current_rxdesc0 = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc0 + ENET_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL(
                      enet_periph))));

__________________________________________________________________________________________________________________________

______________________EXMC________________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/17_EXMC_SDRAM_DeepSleep/main.c

fix reason:
Match the SDRAM bank select macro name modification in the firmware library.

V2.2.0:
sdram_command_init_struct.bank_select = EXMC_SDRAM_DEVICE0;

V2.3.0:
sdram_command_init_struct.bank_select = EXMC_SDRAM_DEVICE0_SELECT;
__________________________________________________________________________________________________________________________

______________________HPDF________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/12_HPDF_I2S_Audio/main.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/12_HPDF_I2S_Audio/gd32h73x_75x_it.c

fix reason:
Change the I2S audio playback from DMA double-buffer mode to SPI1 interrupt
transmit mode, and add timeout mechanism to the DMA transfer flag waiting
loops to avoid dead loops.

V2.2.0:
#define BUFFER_SIZE           1024
#define PLAY_BUFFER_SIZE      BUFFER_SIZE * 2

/* PCM left channel data */
__attribute__((aligned(32))) int32_t pcm_left_data[PLAY_BUFFER_SIZE];
/* PCM right channel data */
__attribute__((aligned(32))) int32_t pcm_right_data[PLAY_BUFFER_SIZE];
/* audio data  */
__attribute__((aligned(32))) int16_t pcm_play_data[2][PLAY_BUFFER_SIZE] = {0};

extern volatile uint8_t g_free_idx;

    /* enable NVIC interrupt request */
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(DMA0_Channel0_IRQn, 1, 1);

    /* configure I2S DMA */
    i2s_dma_config();

    spi_dma_enable(SPI1, SPI_DMA_TRANSMIT);

    while(1) {

        SCB_CleanInvalidateDCache();

        /* wait for DMA full transmit complete */
        while(RESET == dma_flag_get(DMA1, DMA_CH1, DMA_FLAG_FTF));
        while(RESET == dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_FTF));
        /* clear the full transfer complete flag */
        dma_flag_clear(DMA1, DMA_CH1, DMA_FLAG_FTF);
        dma_flag_clear(DMA1, DMA_CH2, DMA_FLAG_FTF);

        /* process entire buffer at once, fill pcm data into free dma buffer */
        for(i = 0; i < BUFFER_SIZE; i++) {
            /* interleave left and right channels */
            pcm_play_data[g_free_idx][2 * i] = DATA_LIMIT((pcm_left_data[i] >> 9), -32768, 32767);
            pcm_play_data[g_free_idx][2 * i + 1] = DATA_LIMIT((pcm_right_data[i] >> 9), -32768, 32767);
        }
    }

void DMA0_Channel0_IRQHandler(void)
{
    if(SET == dma_interrupt_flag_get(DMA0, DMA_CH0, DMA_INT_FLAG_FTF)) {

        dma_interrupt_flag_clear(DMA0, DMA_CH0, DMA_INT_FLAG_FTF);
        /* get current free buffer index for next data processing */
        if(DMA_MEMORY_0 == dma_using_memory_get(DMA0, DMA_CH0)) {
            /* DMA is using buffer 0, so buffer 1 is free */
            g_free_idx = 1;
        } else {
            /* DMA is using buffer 1, so buffer 0 is free */
            g_free_idx = 0;
        }
    }
}

V2.3.0:
#define BUFFER_SIZE           5180
#define PLAY_BUFFER_SIZE      10360

/* PDM left channel data */
__attribute__((aligned(32))) int32_t pcm_left_data[BUFFER_SIZE];
/* PDM right channel data */
__attribute__((aligned(32))) int32_t pcm_right_data[BUFFER_SIZE];
/* audio data  */
__attribute__((aligned(32))) int16_t pcm_play_data[PLAY_BUFFER_SIZE] = {0};

    /* enable interrupt */
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(SPI1_IRQn, 0, 1);

    spi_i2s_interrupt_enable(SPI1, SPI_I2S_INT_TP);

    while(1) {
        SCB_CleanInvalidateDCache();

        /* wait for DMA half-full transmit complete */
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH1, DMA_FLAG_HTF), 300, ret_ch1);
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_HTF), 300, ret_ch2);
        if(ERROR == ret_ch1 || ERROR == ret_ch2) {
            /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
            printf("[ERROR] [%s:%d] DMA_FLAG_HTF get timeout !!!\r\n", __FILE__, __LINE__);
        }

        /* clear the half transfer finish flag */
        dma_flag_clear(DMA1, DMA_CH1, DMA_FLAG_HTF);
        dma_flag_clear(DMA1, DMA_CH2, DMA_FLAG_HTF);

        /* get the PCM stereo data */
        for(i = 0; i < BUFFER_SIZE / 2; i++) {
            pcm_play_data[2 * i] = DATA_LIMIT((pcm_left_data[i] >> 9), -32768, 32767);
            pcm_play_data[(2 * i) + 1] = DATA_LIMIT((pcm_right_data[i] >> 9), -32768, 32767);
        }

        /* wait for DMA full transmit complete */
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH1, DMA_FLAG_FTF), 300, ret_ch1);
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_FTF), 300, ret_ch2);
        if(ERROR == ret_ch1 || ERROR == ret_ch2) {
            /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
            printf("[ERROR] [%s:%d] DMA_FLAG_FTF get timeout !!!\r\n", __FILE__, __LINE__);
        }

        /* clear the full transfer finish flag */
        dma_flag_clear(DMA1, DMA_CH1, DMA_FLAG_FTF);
        dma_flag_clear(DMA1, DMA_CH2, DMA_FLAG_FTF);

        /* get the PCM stereo data */
        for(i = BUFFER_SIZE / 2; i < BUFFER_SIZE; i++) {
            pcm_play_data[2 * i] = DATA_LIMIT((pcm_left_data[i] >> 9), -32768, 32767);
            pcm_play_data[(2 * i) + 1] = DATA_LIMIT((pcm_right_data[i] >> 9), -32768, 32767);
        }
    }

void SPI1_IRQHandler(void)
{
    if(SET == spi_i2s_interrupt_flag_get(SPI1, SPI_I2S_INT_FLAG_TP)) {
        if(send_index >= PLAY_BUFFER_SIZE) {
            send_index = 0;
        }
        spi_i2s_data_transmit(SPI1, pcm_play_data[send_index]);
        send_index++;
    }
}

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/13_HPDF_SAI_Audio/main.c

fix reason:
Add timeout mechanism to the DMA transfer flag waiting loops to avoid dead
loops, and replace the dead loop with error message printing when PLL1 clock
is not stable.

V2.2.0:
    while(1) {
        SCB_CleanInvalidateDCache();
        /* wait for DMA half-full transmit complete */
        while(RESET == dma_flag_get(DMA1, DMA_CH1, DMA_FLAG_HTF));
        while(RESET == dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_HTF));

        /* wait for DMA full transmit complete */
        while(RESET == dma_flag_get(DMA1, DMA_CH1, DMA_FLAG_FTF));
        while(RESET == dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_FTF));

    if(ERROR == rcu_osci_stab_wait(RCU_PLL1_CK)) {
        while(1) {
        }
    }

V2.3.0:
#define DMA_TIMEOUT_MS        1000U

    while(1) {
        SCB_CleanInvalidateDCache();
        /* wait for DMA half-full transmit complete */
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH1, DMA_FLAG_HTF), DMA_TIMEOUT_MS, ret);
        if(ERROR == ret) {
            /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
            printf("[ERROR] [%s:%d] DMA1 channel 1 half-transfer timeout !!!\r\n", __FILE__, __LINE__);
        }
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_HTF), DMA_TIMEOUT_MS, ret);
        if(ERROR == ret) {
            /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
            printf("[ERROR] [%s:%d] DMA1 channel 2 half-transfer timeout !!!\r\n", __FILE__, __LINE__);
        }

        /* wait for DMA full transmit complete */
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH1, DMA_FLAG_FTF), DMA_TIMEOUT_MS, ret);
        if(ERROR == ret) {
            /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
            printf("[ERROR] [%s:%d] DMA1 channel 1 full-transfer timeout !!!\r\n", __FILE__, __LINE__);
        }
        FW_WAIT_WHILE_TIMEOUT(RESET == dma_flag_get(DMA1, DMA_CH2, DMA_FLAG_FTF), DMA_TIMEOUT_MS, ret);
        if(ERROR == ret) {
            /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
            printf("[ERROR] [%s:%d] DMA1 channel 2 full-transfer timeout !!!\r\n", __FILE__, __LINE__);
        }

    if(ERROR == rcu_osci_stab_wait(RCU_PLL1_CK)) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] RCU_PLL1_CK stable timeout !!!\r\n", __FILE__, __LINE__);
    }

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/13_HPDF_SAI_Audio/systick.h

fix reason:
Add the SysTick_Handler function declaration.

V2.2.0:
none

V2.3.0:
/* SysTick exception handler */
void SysTick_Handler(void);

__________________________________________________________________________________________________________________________

______________________OSPI________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/15_OSPI_Octal_Flash/Soft_Drive/gd25x512me.c

fix reason:
Configure both OSPIM port0 and port1 source for OSPI0 and OSPI1.

V2.2.0:
    switch(ospi_periph) {
    case OSPI0:
        rcu_periph_clock_enable(RCU_OSPI0);
        /* configure OSPIM port0 */
        ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI0_SCK);
        ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI0_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI0_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI0_IO_HIGH);
        break;
    case OSPI1:
        rcu_periph_clock_enable(RCU_OSPI1);
        /* configure OSPIM port0 */
        ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI1_SCK);
        ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI1_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI1_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI1_IO_HIGH);
        break;
    default:
        break;

V2.3.0:
    switch(ospi_periph) {
    case OSPI0:
        rcu_periph_clock_enable(RCU_OSPI0);
        /* configure OSPIM */
        ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI0_SCK);
        ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI0_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI0_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI0_IO_HIGH);
        ospim_port_sck_source_select(OSPIM_PORT1, OSPIM_SCK_SOURCE_OSPI1_SCK);
        ospim_port_csn_source_select(OSPIM_PORT1, OSPIM_CSN_SOURCE_OSPI1_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT1, OSPIM_SRCPLIO_OSPI1_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT1, OSPIM_SRCPHIO_OSPI1_IO_HIGH);
        break;
    case OSPI1:
        rcu_periph_clock_enable(RCU_OSPI1);
        /* configure OSPIM */
        ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI1_SCK);
        ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI1_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI1_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI1_IO_HIGH);
        ospim_port_sck_source_select(OSPIM_PORT1, OSPIM_SCK_SOURCE_OSPI0_SCK);
        ospim_port_csn_source_select(OSPIM_PORT1, OSPIM_CSN_SOURCE_OSPI0_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT1, OSPIM_SRCPLIO_OSPI0_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT1, OSPIM_SRCPHIO_OSPI0_IO_HIGH);
        break;
    default:
        break;

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/15_OSPI_Octal_Flash/Soft_Drive/gd25x512me.h
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/15_OSPI_Octal_Flash/Soft_Drive/gd25x512me.c

fix reason:
Add timeout mechanism to the OSPI BUSY flag waiting loop in the memory map
mode enable functions to avoid dead loops, and change the return type of
ospi_flash_memory_map_mode_wrap_enable to ErrStatus.

V2.2.0:
void ospi_flash_memory_map_mode_wrap_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size);

    /* wait BUSY bit to 0 */
    while(RESET != ospi_flag_get(ospi_periph, OSPI_FLAG_BUSY)) {
    }

V2.3.0:
ErrStatus ospi_flash_memory_map_mode_wrap_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size);

    /* wait BUSY bit to 0 */
    FW_WAIT_WHILE_TIMEOUT(RESET != ospi_flag_get(ospi_periph, OSPI_FLAG_BUSY), 100, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] OSPI_FLAG_BUSY get timeout !!!\r\n", __FILE__, __LINE__);
        return ret;
    }

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/15_OSPI_Octal_Flash/main.c

fix reason:
Check the return value of ospi_flash_memory_map_mode_wrap_enable and handle
the timeout error.

V2.2.0:
        ospi_flash_memory_map_mode_wrap_enable(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE);

V2.3.0:
        ret = ospi_flash_memory_map_mode_wrap_enable(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE);
        if(ERROR == ret) {
            printf("OSPI memory mapped mode wrap enable timeout!\r\n");
            while(1){
            }
        }

__________________________________________________________________________________________________________________________

______________________PMU_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/21_PMU_Sleep_Wakeup/gd32h73x_75x_it.h

fix reason:
Add the SysTick_Handler function declaration.

V2.2.0:
none

V2.3.0:
/* this function handles SysTick exception */
void SysTick_Handler(void);

__________________________________________________________________________________________________________________________

______________________RCU_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/20_RCU_Clock_Out/main.c

fix reason:
Replace the dead loops with error message printing when the oscillator
stabilization wait times out, and delete the dead loop in the default case
of the clock output selection.

V2.2.0:
    if(ERROR == rcu_osci_stab_wait(RCU_IRC64M)) {
        printf("RCU_IRC16M rcu_osci_stab_wait timeout! \r\n");
        while(1) {
        }
    }

    if(ERROR == rcu_osci_stab_wait(RCU_HXTAL)) {
        printf("RCU_HXTAL rcu_osci_stab_wait timeout! \r\n");
        while(1) {
        }
    }

    if(ERROR == rcu_osci_stab_wait(RCU_LXTAL)) {
        printf("RCU_LXTAL rcu_osci_stab_wait timeout! \r\n");
        while(1) {
        }
    }

    if(ERROR == rcu_osci_stab_wait(RCU_IRC48M)) {
        printf("RCU_IRC48M rcu_osci_stab_wait timeout! \r\n");
        while(1) {
        }
    }

    if(ERROR == rcu_osci_stab_wait(RCU_IRC32K)) {
        printf("RCU_IRC32K rcu_osci_stab_wait timeout! \r\n");
        while(1) {
        }
    }

    if(ERROR == rcu_osci_stab_wait(RCU_PLL1_CK)) {
        printf("RCU_PLL1_CK rcu_osci_stab_wait timeout! \r\n");
        while(1) {
        }
    }

    if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) {
        printf("RCU_PLL2_CK rcu_osci_stab_wait timeout! \r\n");
        while(1) {
        }
    }

    default:
        printf("clock output select parameter error! \r\n");
        while(1) {
        }
    }

V2.3.0:
    if(ERROR == rcu_osci_stab_wait(RCU_IRC64M)) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] RCU_IRC64M stable timeout !!!\r\n", __FILE__, __LINE__);
    }

    if(ERROR == rcu_osci_stab_wait(RCU_HXTAL)) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] RCU_HXTAL stable timeout !!!\r\n", __FILE__, __LINE__);
    }

    if(ERROR == rcu_osci_stab_wait(RCU_LXTAL)) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] RCU_LXTAL stable timeout !!!\r\n", __FILE__, __LINE__);
    }

    if(ERROR == rcu_osci_stab_wait(RCU_IRC48M)) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] RCU_IRC48M stable timeout !!!\r\n", __FILE__, __LINE__);
    }

    if(ERROR == rcu_osci_stab_wait(RCU_IRC32K)) {
        printf("[ERROR] [%s:%d] RCU_IRC32K stable timeout !!!\r\n", __FILE__, __LINE__);
    }

    if(ERROR == rcu_osci_stab_wait(RCU_PLL1_CK)) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] RCU_PLL1_CK stable timeout !!!\r\n", __FILE__, __LINE__);
    }

    if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) {
        /* once a timeout occurs, user can choose direct return, re-init/reset, retry, or custom action */
        printf("[ERROR] [%s:%d] RCU_PLL2_CK stable timeout !!!\r\n", __FILE__, __LINE__);
    }

    default:
        printf("clock output select parameter error! \r\n");
    }

__________________________________________________________________________________________________________________________

______________________RTC_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/22_RTC_Calendar/main.c

fix reason:
Check the return value of the oscillator stabilization wait in rtc_pre_config
and change its return type to ErrStatus, handle the RTC pre-config failure
in main function.

V2.2.0:
void rtc_pre_config(void);

    rtc_pre_config();

void rtc_pre_config(void)
{
#if defined (RTC_CLOCK_SOURCE_IRC32K)
    rcu_osci_on(RCU_IRC32K);
    rcu_osci_stab_wait(RCU_IRC32K);
    rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);

#elif defined (RTC_CLOCK_SOURCE_LXTAL)
    rcu_osci_on(RCU_LXTAL);
    rcu_osci_stab_wait(RCU_LXTAL);
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

    rcu_periph_clock_enable(RCU_RTC);
    rtc_register_sync_wait();
}

V2.3.0:
ErrStatus rtc_pre_config(void);

    if(ERROR == rtc_pre_config()) {
        printf("\n\r RTC pre-config failed! \n\r");
        while(1) {
        }
    }

ErrStatus rtc_pre_config(void)
{
#if defined (RTC_CLOCK_SOURCE_IRC32K)
    rcu_osci_on(RCU_IRC32K);
    if(ERROR == rcu_osci_stab_wait(RCU_IRC32K)) {
        printf("\n\r RCU_IRC32K stabilization timeout! \n\r");
        return ERROR;
    }
    rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);

#elif defined (RTC_CLOCK_SOURCE_LXTAL)
    rcu_osci_on(RCU_LXTAL);
    if(ERROR == rcu_osci_stab_wait(RCU_LXTAL)) {
        printf("\n\r RCU_LXTAL stabilization timeout! \n\r");
        return ERROR;
    }
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

    rcu_periph_clock_enable(RCU_RTC);
    rtc_register_sync_wait();

    return SUCCESS;
}

__________________________________________________________________________________________________________________________

______________________SPI_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/14_SPI_Quad_LCD/Soft_Drive/spi_quad_lcd_driver.c

fix reason:
Add timeout mechanism to the SPI flag waiting loops in lcd_command_write and
lcd_data_write functions to avoid dead loops.

V2.2.0:
static void lcd_command_write(uint8_t lcd_reg)
{
    while(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TP));
    spi_i2s_data_transmit(LCD_SPI, lcd_reg);
    while(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TC));
}

static void lcd_data_write(uint32_t data)
{
    while(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TP));
    spi_i2s_data_transmit(LCD_SPI, data);
    while(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TC));
}

V2.3.0:
static void lcd_command_write(uint8_t lcd_reg)
{
    ErrStatus ret;

    FW_WAIT_WHILE_TIMEOUT(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TP), 300U, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] SPI_FLAG_TP get timeout !!!\r\n", __FILE__, __LINE__);
        return;
    }
    spi_i2s_data_transmit(LCD_SPI, lcd_reg);
    FW_WAIT_WHILE_TIMEOUT(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TC), 300U, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] SPI_FLAG_TC get timeout !!!\r\n", __FILE__, __LINE__);
        return;
    }
}

static void lcd_data_write(uint32_t data)
{
    ErrStatus ret;

    FW_WAIT_WHILE_TIMEOUT(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TP), 300U, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] SPI_FLAG_TP get timeout !!!\r\n", __FILE__, __LINE__);
        return;
    }
    spi_i2s_data_transmit(LCD_SPI, data);
    FW_WAIT_WHILE_TIMEOUT(RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TC), 300U, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] SPI_FLAG_TC get timeout !!!\r\n", __FILE__, __LINE__);
        return;
    }
}

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/14_SPI_Quad_LCD/main.c

fix reason:
Add MPU configuration function to prevent speculative prefetching of external
memory, which may cause CPU read locks and even system errors, and add USART
configuration for printf.

V2.2.0:
    /* enable the CPU cache */
    cache_enable();
    /* configure systick */
    systick_config();
    /*delay 1 seconds*/
    delay_1ms(1000);
    /* enable peripheral clock */
    rcu_config();
    /* configure GPIO */
    gpio_config();

V2.3.0:
    /* enable the CPU cache */
    cache_enable();
    mpu_config();
    /* configure systick */
    systick_config();
    /*delay 1 seconds*/
    delay_1ms(1000);
    /* enable peripheral clock */
    rcu_config();
    /* USART parameter configuration */
    gd_eval_com_init(EVAL_COM);
    /* configure GPIO */
    gpio_config();

void mpu_config(void)
{
    mpu_region_init_struct mpu_init_struct;
    mpu_region_struct_para_init(&mpu_init_struct);

    /* disable the MPU */
    ARM_MPU_Disable();
    ARM_MPU_SetRegion(0, 0);

    /* configure the MPU attributes for the entire 4GB area, Reserved, no access */
    /* This configuration is highly recommended to prevent Speculative Prefetching of external memory,
       which may cause CPU read locks and even system errors */
    mpu_init_struct.region_base_address  = 0x0;
    mpu_init_struct.region_size          = MPU_REGION_SIZE_4GB;
    mpu_init_struct.access_permission    = MPU_AP_NO_ACCESS;
    mpu_init_struct.access_bufferable    = MPU_ACCESS_NON_BUFFERABLE;
    mpu_init_struct.access_cacheable     = MPU_ACCESS_NON_CACHEABLE;
    mpu_init_struct.access_shareable     = MPU_ACCESS_SHAREABLE;
    mpu_init_struct.region_number        = MPU_REGION_NUMBER0;
    mpu_init_struct.subregion_disable    = 0x87;
    mpu_init_struct.instruction_exec     = MPU_INSTRUCTION_EXEC_NOT_PERMIT;
    mpu_init_struct.tex_type             = MPU_TEX_TYPE0;
    mpu_region_config(&mpu_init_struct);
    mpu_region_enable();

    /* enable the MPU */
    ARM_MPU_Enable(MPU_MODE_PRIV_DEFAULT);
}

__________________________________________________________________________________________________________________________

______________________TLI_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/24_TLI_IPA/main.c

fix reason:
Adjust the TLI layer window left position and frame buffer line length
configuration to fix the display issue.

V2.2.0:
    tli_layer_init_struct.layer_window_leftpos = 80 + HORIZONTAL_SYNCHRONOUS_PULSE +
                                                 HORIZONTAL_BACK_PORCH + 2;

    tli_layer_init_struct.layer_frame_line_length = ((320 * 2) + 3);

    tli_layer_init_struct.layer_window_leftpos = 80 + HORIZONTAL_SYNCHRONOUS_PULSE +
                                                 HORIZONTAL_BACK_PORCH + 2;

    tli_layer_init_struct.layer_frame_line_length = ((247 * 2) + 3);

V2.3.0:
    tli_layer_init_struct.layer_window_leftpos = 80 + HORIZONTAL_SYNCHRONOUS_PULSE +
                                                 HORIZONTAL_BACK_PORCH;

    tli_layer_init_struct.layer_frame_line_length = ((320 * 2) + 7);

    tli_layer_init_struct.layer_window_leftpos = 80 + HORIZONTAL_SYNCHRONOUS_PULSE +
                                                 HORIZONTAL_BACK_PORCH;

    tli_layer_init_struct.layer_frame_line_length = ((247 * 2) + 7);

__________________________________________________________________________________________________________________________

______________________USART_______________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/04_USART_Printf/main.c

fix reason:
Add timeout mechanism to the USART transmission complete flag waiting loops
to avoid dead loops, and adjust the USART configuration before systick
configuration for printf output.

V2.2.0:
    /* configure systick */
    systick_config();

    /* flash the LEDs for 2 time */
    led_flash(2);

    /* configure USART0 */
    usart_config();

    /* wait for completion of USART transmission */
    while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TC)) {
    }

V2.3.0:
    /* configure USART0 */
    usart_config();

    /* configure systick */
    systick_config();

    /* flash the LEDs for 2 times */
    led_flash(2);

    /* wait for completion of USART transmission */
    FW_WAIT_WHILE_TIMEOUT(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TC), 1000U, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] USART_FLAG_TC get timeout !!!\r\n", __FILE__, __LINE__);
    }

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/05_USART_HyperTerminal_Interrupt/main.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/05_USART_HyperTerminal_Interrupt/gd32h73x_75x_it.c

fix reason:
Add timeout mechanism to the USART transmit waiting loop to avoid dead loop,
delete the redundant macro definitions in the interrupt file, and modify the
extern declarations of tx_counter and rx_counter to volatile.

V2.2.0:
    /* wait until USART0 send the tx_buffer */
    while(tx_counter < nbr_data_to_send) {
    }

#define tx_buffer_size   (countof(tx_buffer))
#define countof(a) (sizeof(a)/sizeof(*(a)))
extern uint8_t   tx_buffer[];
extern uint8_t   rx_buffer[] ;
extern uint32_t  nbr_data_to_read, nbr_data_to_send;
extern volatile uint32_t tx_counter, rx_counter;

V2.3.0:
    /* wait until USART0 send the tx_buffer */
    FW_WAIT_WHILE_TIMEOUT(tx_counter < nbr_data_to_send, 1000U, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] USART0 transmit timeout !!!\r\n", __FILE__, __LINE__);
    }

extern uint8_t tx_buffer[];
extern uint8_t rx_buffer[];
extern uint32_t nbr_data_to_read, nbr_data_to_send;
extern volatile uint32_t tx_counter, rx_counter;

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/06_USART_DMA/main.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/06_USART_DMA/gd32h73x_75x_it.c
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/06_USART_DMA/gd32h73x_75x_it.h

fix reason:
Add the independent receive complete flag g_receive_complete to fix the wrong
usage of g_transfer_complete for both transmit and receive completion, add
timeout mechanism to the transmit waiting loop, and refine the buffer size
macro definitions.

V2.2.0:
#define BUFFER_SIZE               96

__IO FlagStatus g_transfer_complete = RESET;

    /* clean d-cache by address before DMA transmission */
    SCB_CleanDCache_by_Addr((uint32_t*)txbuffer, BUFFER_SIZE);

    /* waiting for the transfer to complete*/
    while(RESET == g_transfer_complete) {
    }

    g_transfer_complete = RESET;

    /* waiting for the transfer to complete*/
    while(RESET == g_transfer_complete) {
    }

    /* invalidate d-cache by address after DMA reception*/
    SCB_InvalidateDCache_by_Addr((uint32_t*)rxbuffer, BUFFER_SIZE);
    printf("\n\r%s\n\r", rxbuffer);

    if(RESET != dma_interrupt_flag_get(DMA0, DMA_CH1, DMA_INT_FLAG_FTF)) {
        dma_interrupt_flag_clear(DMA0, DMA_CH1, DMA_INT_FLAG_FTF);
        g_transfer_complete = SET;
    }

V2.3.0:
#define RX_BUFFER_SIZE            32U
#define TX_BUFFER_SIZE            ARRAYNUM(txbuffer)

__IO FlagStatus g_transfer_complete = RESET;
__IO FlagStatus g_receive_complete = RESET;

    /* clean d-cache by address before DMA transmission */
    SCB_CleanDCache_by_Addr((uint32_t*)txbuffer, TX_BUFFER_SIZE);

    /* waiting for the transfer to complete*/
    FW_WAIT_WHILE_TIMEOUT(RESET == g_transfer_complete, 1000U, ret);
    if(ERROR == ret) {
        printf("[ERROR] [%s:%d] DMA transmit timeout !!!\r\n", __FILE__, __LINE__);
    }

    /* waiting for the receive to complete*/
    while(RESET == g_receive_complete);

    /* invalidate d-cache by address after DMA reception*/
    SCB_InvalidateDCache_by_Addr((uint32_t*)rxbuffer, RX_BUFFER_SIZE);
    printf("\n\r%.*s\n\r", ARRAYNUM(rxbuffer), rxbuffer);

    if(RESET != dma_interrupt_flag_get(DMA0, DMA_CH1, DMA_INT_FLAG_FTF)) {
        dma_interrupt_flag_clear(DMA0, DMA_CH1, DMA_INT_FLAG_FTF);
        g_receive_complete = SET;
    }

__________________________________________________________________________________________________________________________

______________________USB_________________________________________________________________________________________________

Fix file:
../GD32H73x_75x_75E_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/27_USB_Device/CDC_ACM/src/gd32h73x_75x_usb_hw.c

fix reason:
Modify the USBHS clock divider from DIV8 to DIV10, and delete the redundant
USBHS clock selection and configuration functions.

V2.2.0:
    if(USBHS0 == usb_periph) {
        rcu_pllusb0_config(RCU_PLLUSBHSPRE_HXTAL, RCU_PLLUSBHSPRE_DIV5, RCU_PLLUSBHS_MUL96, RCU_USBHS_DIV8);
        RCU_ADDCTL1 |= RCU_ADDCTL1_PLLUSBHS0EN;
        while(0U == (RCU_ADDCTL1 & RCU_ADDCTL1_PLLUSBHS0STB)) {
        }

        rcu_usbhs_clock_selection_enable(IDX_USBHS0);
        rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLLUSBHS);
        rcu_usbhs_clock_config(IDX_USBHS0, RCU_USBHSSEL_60M);
    } else {
        rcu_pllusb1_config(RCU_PLLUSBHSPRE_HXTAL, RCU_PLLUSBHSPRE_DIV5, RCU_PLLUSBHS_MUL96, RCU_USBHS_DIV8);
        RCU_ADDCTL1 |= RCU_ADDCTL1_PLLUSBHS1EN;
        while(0U == (RCU_ADDCTL1 & RCU_ADDCTL1_PLLUSBHS1STB)) {
        }

        rcu_usbhs_clock_selection_enable(IDX_USBHS1);
        rcu_usb48m_clock_config(IDX_USBHS1, RCU_USB48MSRC_PLLUSBHS);
        rcu_usbhs_clock_config(IDX_USBHS1, RCU_USBHSSEL_60M);
    }

V2.3.0:
    if(USBHS0 == usb_periph) {
        rcu_pllusb0_config(RCU_PLLUSBHSPRE_HXTAL, RCU_PLLUSBHSPRE_DIV5, RCU_PLLUSBHS_MUL96, RCU_USBHS_DIV10);
        RCU_ADDCTL1 |= RCU_ADDCTL1_PLLUSBHS0EN;
        while(0U == (RCU_ADDCTL1 & RCU_ADDCTL1_PLLUSBHS0STB)) {
        }

        rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLLUSBHS);
    } else {
        rcu_pllusb1_config(RCU_PLLUSBHSPRE_HXTAL, RCU_PLLUSBHSPRE_DIV5, RCU_PLLUSBHS_MUL96, RCU_USBHS_DIV10);
        RCU_ADDCTL1 |= RCU_ADDCTL1_PLLUSBHS1EN;
        while(0U == (RCU_ADDCTL1 & RCU_ADDCTL1_PLLUSBHS1STB)) {
        }

        rcu_usb48m_clock_config(IDX_USBHS1, RCU_USB48MSRC_PLLUSBHS);
    }

__________________________________________________________________________________________________________________________

******************* V2.2.0 2026-02-28 ******************************************************************************************
______________________Common______________________________________________________________________________________________
1. Change the GD32Hxx_Demo_Suites to GD32H3x_75x_Demo_Suites
2. Update the Firmware to V1.5.0
3. Add GD32EmbeddedBuilder Project
4. Update gd32h759i_eval.c, gd32h759i_eval.h
5. Delete the serial port print remapping in main.c

______________________ADC______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/08_ADC0_ADC1_Follow_up_mode/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/09_ADC0_ADC1_Regular_Parallel_mode/main.c

fix reason:
Match firmware library API interface modification

V2.2.0:
    /* ADC channel length config */
    adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2);
    adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 2);

    /* ADC regular channel config */
    adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_0, 240);
    adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_18, 240);
    adc_regular_channel_config(ADC1, 0, ADC_CHANNEL_18, 240);
    adc_regular_channel_config(ADC1, 1, ADC_CHANNEL_0, 240);

    /* ADC trigger config */
    trigsel_init(TRIGSEL_OUTPUT_ADC0_REGTRG, TRIGSEL_INPUT_TIMER1_CH1);
    adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_RISING);

    /* configure the ADC sync mode */
    adc_sync_mode_config(ADC_DAUL_REGULAL_FOLLOW_UP);
V2.1.0:
    /* ADC channel length config */
    adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 2);
    adc_channel_length_config(ADC1, ADC_ROUTINE_CHANNEL, 2);

    /* ADC routine channel config */
    adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_0, 240);
    adc_routine_channel_config(ADC0, 1, ADC_CHANNEL_18, 240);
    adc_routine_channel_config(ADC1, 0, ADC_CHANNEL_18, 240);
    adc_routine_channel_config(ADC1, 1, ADC_CHANNEL_0, 240);

    /* ADC trigger config */
    trigsel_init(TRIGSEL_OUTPUT_ADC0_ROUTRG, TRIGSEL_INPUT_TIMER1_CH1);
    adc_external_trigger_config(ADC0, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_RISING);

    /* configure the ADC sync mode */
    adc_sync_mode_config(ADC_DAUL_ROUTINE_FOLLOW_UP);

______________________HPDF______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/12_HPDF_I2S_Audio/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/12_HPDF_I2S_Audio/GD32H73x_75x_it.c

fix reason:
Modify the I2S playback method from interrupt-based playback to DMA-based I2S playback

______________________SPI______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/14_SPI_Quad_LCD/main.c

fix reason:
Delete spi_quad_io23_output_enable(LCD_SPI)

______________________EXMC______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/16_EXMC_SDRAM/Soft_Drive/exmc_sdram.h
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/16_EXMC_SDRAM/Soft_Drive/exmc_sdram.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/17_EXMC_SDRAM_DeepSleep/Soft_Drive/exmc_sdram.h
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/17_EXMC_SDRAM_DeepSleep/Soft_Drive/exmc_sdram.c

fix reason:
Update EXMC SDRAM comments and parameters

V2.2.0
    /* SDCLK_Freq = SYS_Freq/3 */
    /* (7.81 us * SDCLK_Freq) - 20 */
    exmc_sdram_refresh_count_set(760);
V2.1.0
    /* SDCLK_Freq = SYS_Freq/2 */
    /* (7.81 us * SDCLK_Freq) - 20 */
    exmc_sdram_refresh_count_set(1542);

______________________SDIO______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/18_SDIO_SDCardTest/Soft_Drive/sdcard.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/18_SDIO_SDCardTest/Soft_Drive/sdcard.h

fix reason:
spelling mistake

V2.2.0:
    #define SD_CARDSTATE_IDENTIFICATION         ((uint8_t)0x02)
V2.1.0:
    #define SD_CARDSTATE_IDENTIFICAT            ((uint8_t)0x02)

V2.2.0:
    #define SD_CMD_VOLTAGE_SWITCH                 ((uint8_t)11)
V2.1.0:
    #define SD_CMD_VOLATAGE_SWITCH                ((uint8_t)11)

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/18_SDIO_SDCardTest/Soft_Drive/sdcard.c

fix reason:
Fix the bug of register parameter configuration order

V2.2.0:
    sdio_data_transfer_config(SDIO, SDIO_TRANSMODE_BLOCKCOUNT, SDIO_TRANSDIRECTION_TOSDIO);
V2.1.0:
    sdio_data_transfer_config(SDIO, SDIO_TRANSDIRECTION_TOSDIO, SDIO_TRANSMODE_BLOCKCOUNT);

______________________CAN______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/19_CAN_Network/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/19_CAN_Network/gd32h73x_75x_it.c

fix reason:
Adjust the logic of the CAN controller for reading data

V2.2.0:
void communication_check(void)
{
    uint8_t i = 0U;
    /* CAN1 receive data correctly, the received data is printed */
    if(SET == can1_receive_flag) {
        can1_receive_flag = RESET;
        if(0U == memcmp(rx_data, tx_data, receive_message.data_bytes)) {
            printf("\r\nCAN1 receive data: \r\n");
            for(i = 0U; i < receive_message.data_bytes; i++) {
                printf("%02x ", rx_data[i]);
            }
            gd_eval_led_toggle(LED2);
        }
    }
}
V2.1.0:
void communication_check(void)
{
    uint8_t i = 0U;
    /* CAN1 receive data correctly, the received data is printed */
    if(SET == can1_receive_flag) {
        can1_receive_flag = RESET;

        /* check the receive message */
        can_mailbox_receive_data_read(CAN1, 0U, &receive_message);
        if(0U == memcmp(rx_data, tx_data, receive_message.data_bytes)) {
            printf("\r\nCAN1 receive data: \r\n");
            for(i = 0U; i < receive_message.data_bytes; i++) {
                printf("%02x ", rx_data[i]);
            }
            gd_eval_led_toggle(LED2);
        }
    }
}

V2.2.0:
void CAN1_Message_IRQHandler(void)
{
    if(RESET != can_interrupt_flag_get(CAN1, CAN_INT_FLAG_MB0)) {
        /* read the receive message */
        can_mailbox_receive_data_read(CAN1, 0U, &receive_message);
        can1_receive_flag = SET;
    }
}
V2.1.0:
void CAN1_Message_IRQHandler(void)
{
    if(RESET != can_interrupt_flag_get(CAN1, CAN_INT_FLAG_MB0)) {
        can_interrupt_flag_clear(CAN1, CAN_INT_FLAG_MB0);
        can1_receive_flag = SET;
    }
}

______________________TLI______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/24_TLI_IPA/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/29_TLI_Touch_Draw/main.c

fix reason:
spelling mistake 

V2.2.0:
    tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTIVE_LOW;
    tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTIVE_LOW;
    tli_init_struct.signalpolarity_de = TLI_DE_ACTIVE_LOW;
    tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;
V2.1.0:
    tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;
    tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;
    tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW;
    tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;

______________________DCI______________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects//25_DCI_OV2640/main.c

fix reason:
spelling mistake 

V2.2.0:
    /* configure PLL2 to generate TLI clock 25MHz/25*186/3 = 62MHz */
    rcu_pll_input_output_clock_range_config(IDX_PLL2, RCU_PLL2RNG_1M_2M, RCU_PLL2VCO_150M_420M);
    if(ERROR == rcu_pll2_config(25, 186, 3, 3, 3)) {
        while(1) {
        }
    }
V2.0.0
    /* configure PLL2 to generate TLI clock 25MHz/25*120/3 = 40MHz */
    rcu_pll_input_output_clock_range_config(IDX_PLL2, RCU_PLL2RNG_1M_2M, RCU_PLL2VCO_150M_420M);
    if(ERROR == rcu_pll2_config(25, 120, 3, 3, 3)) {
        while(1) {
        }
    }

../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/25_DCI_OV2640/Soft_Drive/dci_ov2640.c
fix reason:
bug fix
V1.2.0:
    rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL, RCU_CKOUT0_DIV2);
V2.0.0
    rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL, RCU_CKOUT0_DIV3);

../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/25_DCI_OV2640/Soft_Drive/dci_ov2640.c
fix reason:
bug fix
V1.2.0:
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_3);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4);

    /* configure  DCI_D0(PC6), DCI_D1(PH10) DCI_D2(PC8), DCI_D3(PC9), DCI_D4(PE4), DCI_D5(PB6), DCI_D6(PE5), DCI_D7(PE6) */
    gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_6);
    gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_8);
    gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_9);
    gpio_af_set(GPIOB, GPIO_AF_13, GPIO_PIN_6);
    gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_4);
    gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_5);
    gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_6);
    gpio_af_set(GPIOH, GPIO_AF_13, GPIO_PIN_10);

    gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10);

    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);

    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_5);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
V2.0.0:
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_3);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_7);

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_4);

    /* configure  DCI_D0(PC6), DCI_D1(PH10) DCI_D2(PC8), DCI_D3(PC9), DCI_D4(PE4), DCI_D5(PB6), DCI_D6(PE5), DCI_D7(PE6) */
    gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_6);
    gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_8);
    gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_9);
    gpio_af_set(GPIOB, GPIO_AF_13, GPIO_PIN_6);
    gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_4);
    gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_5);
    gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_6);
    gpio_af_set(GPIOH, GPIO_AF_13, GPIO_PIN_10);

    gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_10);

    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_6);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_9);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_8);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_6);

    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_4);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_5);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_85MHZ, GPIO_PIN_6);
__________________________________________________________________________________________________________________________

__________________________________________________________________________________________________________________________

______________________EXMC________________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/16_EXMC_SDRAM/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/17_EXMC_SDRAM_DeepSleep/main.c
fix reason:
bug fix
V1.2.0
#define BUFFER_SIZE                ((uint32_t)0x0400)
#define WRITE_READ_ADDR            ((uint32_t)0x0000)
V2.0.0
#define BUFFER_SIZE                ((uint32_t)0x8000)
#define WRITE_READ_ADDR            ((uint32_t)0x7FFF00)

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/16_EXMC_SDRAM/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/17_EXMC_SDRAM_DeepSleep/main.c
fix reason:
bug fix
V1.2.0
    exmc_sdram_command_parameter_struct     sdram_command_init_struct;
    uint16_t i = 0;

    /* initialize LEDs */
    gd_eval_led_init(LED1);
    gd_eval_led_init(LED2);
V2.0.0
    exmc_sdram_command_parameter_struct     sdram_command_init_struct;
    uint16_t i = 0;

    /* enable the CPU cache */
    cache_enable();
    /* configure MPU */
    mpu_config();

    /* initialize LEDs */
    gd_eval_led_init(LED1);
    gd_eval_led_init(LED2);

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/16_EXMC_SDRAM/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/17_EXMC_SDRAM_DeepSleep/main.c
fix reason:
bug fix
V1.2.0
void cache_enable(void)
{
    /* enable I-Cache */
    SCB_EnableICache();

    /* enable D-Cache */
    SCB_EnableDCache();
}
V2.0.0
static void cache_enable(void)
{
    /* enable I-Cache and D-Cache */
    SCB_EnableICache();
    SCB_EnableDCache();
}

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/16_EXMC_SDRAM/main.c
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/17_EXMC_SDRAM_DeepSleep/main.c
fix reason:
bug fix
V1.2.0
none
V2.0.0
/*!
    \brief      configure the MPU attributes
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void mpu_config(void)
{
    mpu_region_init_struct mpu_init_struct;
    mpu_region_struct_para_init(&mpu_init_struct);

    /* disable the MPU */
    ARM_MPU_Disable();
    ARM_MPU_SetRegion(0, 0);
    
    /* configure the MPU attributes for Reserved, no access */
    mpu_init_struct.region_base_address  = 0x0;
    mpu_init_struct.region_size          = MPU_REGION_SIZE_4GB;
    mpu_init_struct.access_permission    = MPU_AP_NO_ACCESS;
    mpu_init_struct.access_bufferable    = MPU_ACCESS_NON_BUFFERABLE;
    mpu_init_struct.access_cacheable     = MPU_ACCESS_NON_CACHEABLE;
    mpu_init_struct.access_shareable     = MPU_ACCESS_SHAREABLE;
    mpu_init_struct.region_number        = MPU_REGION_NUMBER0;
    mpu_init_struct.subregion_disable    = 0x87;
    mpu_init_struct.instruction_exec     = MPU_INSTRUCTION_EXEC_NOT_PERMIT;
    mpu_init_struct.tex_type             = MPU_TEX_TYPE0;
    mpu_region_config(&mpu_init_struct);
    mpu_region_enable();
    
    /* configure the MPU attributes for SDRAM */
    mpu_init_struct.region_base_address  = 0xC0000000;
    mpu_init_struct.region_size          = MPU_REGION_SIZE_32MB;
    mpu_init_struct.access_permission    = MPU_AP_FULL_ACCESS;
    mpu_init_struct.access_bufferable    = MPU_ACCESS_NON_BUFFERABLE;
    mpu_init_struct.access_cacheable     = MPU_ACCESS_CACHEABLE;
    mpu_init_struct.access_shareable     = MPU_ACCESS_NON_SHAREABLE;
    mpu_init_struct.region_number        = MPU_REGION_NUMBER1;
    mpu_init_struct.subregion_disable    = 0x0;
    mpu_init_struct.instruction_exec     = MPU_INSTRUCTION_EXEC_NOT_PERMIT;
    mpu_init_struct.tex_type             = MPU_TEX_TYPE0;
    mpu_region_config(&mpu_init_struct);
    mpu_region_enable();
    
    /* enable the MPU */
    ARM_MPU_Enable(MPU_MODE_PRIV_DEFAULT);
}
__________________________________________________________________________________________________________________________


______________________OSPI________________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/15_OSPI_Octal_Flash/Soft_Drive/gd25x512me.c
fix reason:
modify the OSPI function pin for gd32h73x_75x_eval_2.0 board
V1.2.0:
    /* enable OSPIM and GPIO clock */
    rcu_periph_clock_enable(RCU_OSPIM);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_GPIOE);

    /* configure OSPIM GPIO pin:
           OSPIM_P0_IO0(PD11)
           OSPIM_P0_IO1(PC10)
           OSPIM_P0_IO2(PE2)
           OSPIM_P0_IO3(PD13)
           OSPIM_P0_IO4(PD4)
           OSPIM_P0_IO5(PD5)
           OSPIM_P0_IO6(PD6)
           OSPIM_P0_IO7(PD7)
           OSPIM_P0_CLK(PA3)
           OSPIM_P0_NCS(PB10) */

    gpio_af_set(GPIOA, GPIO_AF_12, GPIO_PIN_3);
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);

    gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_10);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);

    gpio_af_set(GPIOC, GPIO_AF_9, GPIO_PIN_10);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);

    gpio_af_set(GPIOD, GPIO_AF_10, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);

    gpio_af_set(GPIOD, GPIO_AF_9, GPIO_PIN_11 | GPIO_PIN_13);
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_13);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11 | GPIO_PIN_13);

    gpio_af_set(GPIOE, GPIO_AF_9, GPIO_PIN_2);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_2);

    /* enable SCK, CSN, IO[3:0] and IO[7:4] for OSPIM port0 */
    ospim_port_sck_config(OSPIM_PORT0, OSPIM_PORT_SCK_ENABLE);
    ospim_port_csn_config(OSPIM_PORT0, OSPIM_PORT_CSN_ENABLE);
    ospim_port_io3_0_config(OSPIM_PORT0, OSPIM_IO_LOW_ENABLE);
    ospim_port_io7_4_config(OSPIM_PORT0, OSPIM_IO_HIGH_ENABLE);
V2.0.0:
    /* enable OSPIM and GPIO clock */
    rcu_periph_clock_enable(RCU_OSPIM);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOD);

        /* configure OSPIM GPIO pin:
           OSPIM_P0_IO0(PD11) AF9
           OSPIM_P0_IO1(PD12) AF9
           OSPIM_P0_IO2(PA3)  AF6
           OSPIM_P0_IO3(PD13) AF9
           OSPIM_P0_IO4(PD4)  AF10
           OSPIM_P0_IO5(PD5)  AF10
           OSPIM_P0_IO6(PD6)  AF10
           OSPIM_P0_IO7(PD7)  AF10
           OSPIM_P0_CLK(PB2)  AF9
           OSPIM_P0_NCS(PB6)  AF10  */

        gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_2);
        gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
        gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_2);

        gpio_af_set(GPIOA, GPIO_AF_6, GPIO_PIN_3);
        gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
        gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_3);

        gpio_af_set(GPIOD, GPIO_AF_10, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
        gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
        gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);

        gpio_af_set(GPIOD, GPIO_AF_9, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);
        gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);
        gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);

        gpio_af_set(GPIOB, GPIO_AF_10, GPIO_PIN_6);
        gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
        gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);

        /* enable SCK, CSN, IO[3:0] and IO[7:4] for OSPIM port0 */
        ospim_port_sck_config(OSPIM_PORT0, OSPIM_PORT_SCK_ENABLE);
        ospim_port_csn_config(OSPIM_PORT0, OSPIM_PORT_CSN_ENABLE);
        ospim_port_io3_0_config(OSPIM_PORT0, OSPIM_IO_LOW_ENABLE);
        ospim_port_io7_4_config(OSPIM_PORT0, OSPIM_IO_HIGH_ENABLE);
__________________________________________________________________________________________________________________________


______________________SDIO________________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/18_SDIO_SDCardTest/main.c
fix reason:
bug fix
V1.2.0:
void card_info_get(void)
{
    uint8_t sd_spec, sd_spec3, sd_spec4, sd_security;
    uint32_t block_count, block_size, sd_capacity;
    uint16_t temp_ccc;
    printf("\r\n Card information:");
    sd_spec = (sd_scr[1] & 0x0F000000) >> 24;
    sd_spec3 = (sd_scr[1] & 0x00008000) >> 15;
    sd_spec4 = (sd_scr[1] & 0x00000400) >> 10;
    if(2 == sd_spec) {
        if(1 == sd_spec3) {
            if(1 == sd_spec4) {
                printf("\r\n## Card version 4.xx ##");
            } else {
                printf("\r\n## Card version 3.0x ##");
            }
        } else {
            printf("\r\n## Card version 2.00 ##");
        }
    } else if(1 == sd_spec) {
        printf("\r\n## Card version 1.10 ##");
    } else if(0 == sd_spec) {
        printf("\r\n## Card version 1.0x ##");
    }

    sd_security = (sd_scr[1] & 0x00700000) >> 20;
    if(2 == sd_security) {
        printf("\r\n## security v1.01 ##");
    } else if(3 == sd_security) {
        printf("\r\n## security v2.00 ##");
    } else if(4 == sd_security) {
        printf("\r\n## security v3.00 ##");
    }

    block_size = 512U;
    sd_capacity = sd_card_capacity_get();
    block_count = sd_capacity * 2U;
    printf("\r\n## Device size is %dKB ##", sd_capacity);
    printf("\r\n## Block size is %dB ##", block_size);
    printf("\r\n## Block count is %d ##", block_count);

    if(sd_cardinfo.card_csd.read_bl_partial) {
        printf("\r\n## Partial blocks for read allowed ##");
    }
    if(sd_cardinfo.card_csd.write_bl_partial) {
        printf("\r\n## Partial blocks for write allowed ##");
    }
    temp_ccc = sd_cardinfo.card_csd.ccc;
    printf("\r\n## CardCommandClasses is: %x ##", temp_ccc);
    if((SD_CCC_BLOCK_READ & temp_ccc) && (SD_CCC_BLOCK_WRITE & temp_ccc)) {
        printf("\r\n## Block operation supported ##");
    }
    if(SD_CCC_ERASE & temp_ccc) {
        printf("\r\n## Erase supported ##");
    }
    if(SD_CCC_WRITE_PROTECTION & temp_ccc) {
        printf("\r\n## Write protection supported ##");
    }
    if(SD_CCC_LOCK_CARD & temp_ccc) {
        printf("\r\n## Lock unlock supported ##");
    }
    if(SD_CCC_APPLICATION_SPECIFIC & temp_ccc) {
        printf("\r\n## Application specific supported ##");
    }
    if(SD_CCC_IO_MODE & temp_ccc) {
        printf("\r\n## I/O mode supported ##");
    }
    if(SD_CCC_SWITCH & temp_ccc) {
        printf("\r\n## Switch function supported ##");
    }
}
V2.0.0:
void card_info_get(void)
{
    uint8_t sd_spec, sd_spec3, sd_spec4, sd_security;
    uint32_t block_count, block_size, sd_capacity;
    uint16_t temp_ccc;
    printf("\r\n Card information:");
    sd_spec = (sd_scr[1] & 0x0F000000) >> 24;
    sd_spec3 = (sd_scr[1] & 0x00008000) >> 15;
    sd_spec4 = (sd_scr[1] & 0x00000400) >> 10;
    if(2 == sd_spec) {
        if(1 == sd_spec3) {
            if(1 == sd_spec4) {
                printf("\r\n## Card version 4.xx ##");
            } else {
                printf("\r\n## Card version 3.0x ##");
            }
        } else {
            printf("\r\n## Card version 2.00 ##");
        }
    } else if(1 == sd_spec) {
        printf("\r\n## Card version 1.10 ##");
    } else if(0 == sd_spec) {
        printf("\r\n## Card version 1.0x ##");
    }

    sd_security = (sd_scr[1] & 0x00700000) >> 20;
    if(2 == sd_security) {
        printf("\r\n## security v1.01 ##");
    } else if(3 == sd_security) {
        printf("\r\n## security v2.00 ##");
    } else if(4 == sd_security) {
        printf("\r\n## security v3.00 ##");
    }

    block_size = 512U;
    sd_capacity = sd_card_capacity_get();
    block_count = sd_capacity * 2U;
    printf("\r\n## Device size is %dKB ##", sd_capacity);
    printf("\r\n## Block size is %dB ##", block_size);
    printf("\r\n## Block count is %d ##", block_count);

    if(sd_cardinfo.card_csd.read_bl_partial) {
        printf("\r\n## Partial blocks for read allowed ##");
    }
    if(sd_cardinfo.card_csd.write_bl_partial) {
        printf("\r\n## Partial blocks for write allowed ##");
    }
    temp_ccc = sd_cardinfo.card_csd.ccc;
    printf("\r\n## CardCommandClasses is: %x ##", temp_ccc);
    if((SD_CCC_BLOCK_READ & temp_ccc) && (SD_CCC_BLOCK_WRITE & temp_ccc)) {
        printf("\r\n## Block operation supported ##");
    }
    if(SD_CCC_ERASE & temp_ccc) {
        printf("\r\n## Erase supported ##");
    }
    if(SD_CCC_WRITE_PROTECTION & temp_ccc) {
        printf("\r\n## Write protection supported ##");
    }
    if(SD_CCC_LOCK_CARD & temp_ccc) {
        printf("\r\n## Lock unlock supported ##");
    }
    if(SD_CCC_APPLICATION_SPECIFIC & temp_ccc) {
        printf("\r\n## Application specific supported ##");
    }
    if(SD_CCC_IO_MODE & temp_ccc) {
        printf("\r\n## I/O mode supported ##");
    }
    if(SD_CCC_SWITCH & temp_ccc) {
        printf("\r\n## Switch function supported ##");
    }
}
__________________________________________________________________________________________________________________________

__________________________________________________________________________________________________________________________

______________________TLI_________________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/24_TLI_IPA/main.c
fix reason:
bug fix
V1.2.0
    gpio_af_set(GPIOE, GPIO_AF_14, GPIO_PIN_15);
V1.2.0
    gpio_af_set(GPIOE, GPIO_AF_10, GPIO_PIN_15);

__________________________________________________________________________________________________________________________

__________________________________________________________________________________________________________________________

_____________________USBFS________________________________________________________________________________________________
Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/28_USB_Host/Host_HID/inc/usb_conf.h
fix reason:
bug fix
V1.2.0:
#define USB_SOF_OUTPUT                        1U
V2.0.0:
#define USB_SOF_OUTPUT                        0U

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/28_USB_Host/Host_HID/inc/gd32h73x_75x_it.c
fix reason:
bug fix
V1.2.0:
none
V2.0.0:
#if USB_LOW_POWER

/*!
    \brief      this function handles external line 0 interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void EXTI0_IRQHandler(void)
{
    if (exti_interrupt_flag_get(WAKEUP_KEY_EXTI_LINE) != RESET) {
        if (hid_keyboard.bp.low_power) {
            resume_mcu_clk();

            #ifndef USE_IRC48M
                rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLL0R);
            #else
                /* enable IRC48M clock */
                rcu_osci_on(RCU_IRC48M);

                /* wait till IRC48M is ready */
                while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) {
                }

                rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M);
            #endif /* USE_IRC48M */

            rcu_periph_clock_enable(RCU_USBHS0);

            usb_clock_active(&hid_keyboard);

            usb_rwkup_set(&hid_keyboard);

            /* add delay time */
            for(__IO uint16_t i = 0; i < 1000; i++){
                for(__IO uint16_t i = 0; i < 200; i++);
            }

            usb_rwkup_reset(&hid_keyboard);

            hid_keyboard.dev.cur_status = hid_keyboard.dev.backup_status;

            hid_keyboard.dev.pm.dev_remote_wakeup = 0U;
        }

        /* clear the EXTI line pending bit */
        exti_interrupt_flag_clear(WAKEUP_KEY_EXTI_LINE);
    }
}

#endif /* USB_LOW_POWER */

/*!
    \brief      this function handles USBHS wakeup interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
#ifdef USE_USBHS0

void USBHS0_WKUP_IRQHandler(void)
{
    if (hid_keyboard.bp.low_power) {
        resume_mcu_clk();

        rcu_periph_clock_enable(RCU_USBHS0);

        #ifndef USE_IRC48M
           rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLL0R);
        #else
            /* enable IRC48M clock */
            rcu_osci_on(RCU_IRC48M);

            /* wait till IRC48M is ready */
            while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) {
            }

            rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M);
        #endif /* USE_IRC48M */

        usb_clock_active(&hid_keyboard);
    }

    exti_interrupt_flag_clear(EXTI_31);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1

void USBHS1_WKUP_IRQHandler(void)
{
    if (hid_keyboard.bp.low_power) {
        resume_mcu_clk();

        #ifndef USE_IRC48M
            rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLL0R);
        #else
            /* enable IRC48M clock */
            rcu_osci_on(RCU_IRC48M);

            /* wait till IRC48M is ready */
            while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) {
            }

            rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M);
        #endif /* USE_IRC48M */

        rcu_periph_clock_enable(RCU_USBHS1);

        usb_clock_active(&hid_keyboard);
    }

    exti_interrupt_flag_clear(EXTI_32);
}

#endif /* USE_USBHS1 */

#ifdef USB_DEDICATED_EP1_ENABLED

/*!
    \brief      this function handles USB dedicated endpoint 1 OUT interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
#ifdef USE_USBHS0

void USBHS0_EP1_OUT_IRQHandler (void)
{
    usbd_int_dedicated_ep1out(&hid_keyboard);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1

void USBHS1_EP1_OUT_IRQHandler (void)
{
    usbd_int_dedicated_ep1out(&hid_keyboard);
}

#endif /* USE_USBHS1 */

/*!
    \brief      this function handles USB dedicated endpoint 1 IN interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
#ifdef USE_USBHS0

void USBHS0_EP1_IN_IRQHandler (void)
{
    usbd_int_dedicated_ep1in(&hid_keyboard);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1

void USBHS1_EP1_IN_IRQHandler (void)
{
    usbd_int_dedicated_ep1in(&hid_keyboard);
}

#endif /* USE_USBHS1 */

#endif /* USB_DEDICATED_EP1_ENABLED */

/*!
    \brief      this function handles Timer2 update interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void TIMER2_IRQHandler(void)
{
    usb_timer_irq();
}

#ifdef USE_USBHS0
/*!
    \brief      this function handles USBHS0 interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS0_IRQHandler(void)
{
    usbh_isr (&hid_host_core);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1
/*!
    \brief      this function handles USBHS1 interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS1_IRQHandler(void)
{
    usbh_isr (&hid_host_core);
}

#endif /* USE_USBHS1 */

#ifdef USE_USBHS0
/*!
    \brief      this function handles USBHS0 wakeup interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS0_WKUP_IRQHandler(void)
{
    if(1U == usb_host_hid.suspend_flag) {
        usb_host_hid.suspend_flag = 0U;

        /* configure system clock */
        resume_mcu_clk();

        usb_rcu_config();

        usb_host_hid.wakeup_mode = REMOTE_WAKEUP; /* remote wakeup mode */

#ifdef USE_USB_HS
        /* configure usb clock */
        pllusb_rcu_config(USBHS0);
#endif /* USE_USB_HS */
    }

    exti_interrupt_flag_clear(EXTI_31);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1
/*!
    \brief      this function handles USBHS1 wakeup interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS1_WKUP_IRQHandler(void)
{
    if(1U == usb_host_hid.suspend_flag) {
        usb_host_hid.suspend_flag = 0U;
        usb_host_hid.wakeup_mode = REMOTE_WAKEUP; /* remote wakeup mode */

        /* configure system clock */
        resume_mcu_clk();

        usb_rcu_config();

#ifdef USE_USB_HS
        /* configure usb clock */
        pllusb_rcu_config(USBHS1);
#endif /* USE_USB_HS */
    }

    exti_interrupt_flag_clear(EXTI_32);
}

#endif /* USE_USBHS1 */

#if USB_LOW_POWER

/*!
    \brief      this function handles external line 0 interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void EXTI0_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(WAKEUP_KEY_EXTI_LINE)) {
        if(1U == usb_host_hid.suspend_flag) {
            usb_host_hid.suspend_flag = 0U;
            usb_host_hid.wakeup_mode = GENERAL_WAKEUP; /* general wakeup mode */

            /* configure system clock */
            resume_mcu_clk();

            usb_rcu_config();

#ifdef USE_USB_HS
    #ifdef USE_USBHS0
        pllusb_rcu_config(USBHS0);
    #elif defined USE_USBHS1
        pllusb_rcu_config(USBHS1);
    #else
    #endif
#endif /* USE_USB_HS */
        }

        /* clear the EXTI line pending bit */
        exti_interrupt_flag_clear(WAKEUP_KEY_EXTI_LINE);
    }
}

#endif /* USB_LOW_POWER */

/*!
    \brief      this function handles USBHS wakeup interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
#ifdef USE_USBHS0

void USBHS0_WKUP_IRQHandler(void)
{
    if (hid_keyboard.bp.low_power) {
        resume_mcu_clk();

        rcu_periph_clock_enable(RCU_USBHS0);

        #ifndef USE_IRC48M
           rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLL0R);
        #else
            /* enable IRC48M clock */
            rcu_osci_on(RCU_IRC48M);

            /* wait till IRC48M is ready */
            while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) {
            }

            rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M);
        #endif /* USE_IRC48M */

        usb_clock_active(&hid_keyboard);
    }

    exti_interrupt_flag_clear(EXTI_31);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1

void USBHS1_WKUP_IRQHandler(void)
{
    if (hid_keyboard.bp.low_power) {
        resume_mcu_clk();

        #ifndef USE_IRC48M
            rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLL0R);
        #else
            /* enable IRC48M clock */
            rcu_osci_on(RCU_IRC48M);

            /* wait till IRC48M is ready */
            while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) {
            }

            rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M);
        #endif /* USE_IRC48M */

        rcu_periph_clock_enable(RCU_USBHS1);

        usb_clock_active(&hid_keyboard);
    }

    exti_interrupt_flag_clear(EXTI_32);
}

#endif /* USE_USBHS1 */

#ifdef USB_DEDICATED_EP1_ENABLED

#ifdef USE_USBHS0
/*!
    \brief      this function handles USBHS0 dedicated endpoint 1 OUT interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS0_EP1_OUT_IRQHandler(void)
{
    usbd_int_dedicated_ep1out(&hid_keyboard);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1
/*!
    \brief      this function handles USBHS1 dedicated endpoint 1 OUT interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS1_EP1_OUT_IRQHandler(void)
{
    usbd_int_dedicated_ep1out(&hid_keyboard);
}

#endif /* USE_USBHS1 */

#ifdef USE_USBHS0
/*!
    \brief      this function handles USBHS0 dedicated endpoint 1 IN interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS0_EP1_IN_IRQHandler(void)
{
    usbd_int_dedicated_ep1in(&hid_keyboard);
}

#endif /* USE_USBHS0 */

#ifdef USE_USBHS1
/*!
    \brief      this function handles USBHS1 dedicated endpoint 1 IN interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USBHS1_EP1_IN_IRQHandler(void)
{
    usbd_int_dedicated_ep1in(&hid_keyboard);
}

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/28_USB_Host/Host_HID/src/usbh_usr.c
fix reason:
bug fix
V1.2.0:
#include "usbh_usr.h"
#include "usbh_hid_core.h"
#include "usbh_hid_mouse.h"
V2.0.0
#include "usbh_usr.h"
#include "usbh_hid_core.h"
#include "usbh_standard_hid.h"

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/28_USB_Host/Host_HID/src/usbh_usr.c
fix reason:
bug fix
V1.2.0:
void usbh_user_configuration_descavailable(usb_desc_config *cfg_desc,
                                           usb_desc_itf *itf_desc,
                                           usb_desc_ep *ep_desc)
{
    usb_desc_itf *id = itf_desc;

    if (0x08U == (*id).bInterfaceClass) {
        LCD_UsrLog("> Mass storage device connected.\r\n");
    } else if (0x03U == (*id).bInterfaceClass) {
        LCD_UsrLog("> HID device connected.\r\n");
    }
}
V2.0.0
void usbh_user_configuration_descavailable(usb_desc_config *cfg_desc, \
                                           usb_desc_itf *itf_desc, \
                                           usb_desc_ep *ep_desc)
{
    usb_desc_itf *id = itf_desc;

    if(0x08U == (*id).bInterfaceClass) {
        LCD_UsrLog("> Mass storage device connected.\r\n");
    } else if(0x03U == (*id).bInterfaceClass) {
        LCD_UsrLog("> HID device connected.\r\n");
    } else {
        LCD_UsrLog("> Unknown device connected.\r\n");
    }
}

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/28_USB_Host/Host_HID/src/usbh_usr.c
fix reason:
bug fix
V1.2.0:
usbh_user_status usbh_user_userinput(void)
{
    usbh_user_status usbh_usr_status = USBH_USER_NO_RESP;

#if USB_LOW_POWER
    gd_eval_key_init(KEY_WAKEUP, KEY_MODE_EXTI);

    if (usb_host_hid.suspend_flag){
        LCD_UsrLog("\n> Pls press Tamper key to make the USB host enter the suspended state.\n");
        LCD_UsrLog("\n> To wake up the USB host, pls press WAKEUP key (General wakeup).\n");

        if(usb_host_hid.dev_supp_remote_wkup){
            LCD_UsrLog("> Or operate device (Remote wakeup).\n");
        }

        /* wait for Tamper key pressed */
        while(SET == gd_eval_key_state_get(KEY_TAMPER));
    } else {
        if (usb_host_hid.wakeup_mode == 1) {
            usb_host_hid.wakeup_mode = 0;
            LCD_UsrLog("> General wakeup success.\r\n");
        } else if (usb_host_hid.wakeup_mode == 2) {
            usb_host_hid.wakeup_mode = 0;
            LCD_UsrLog("> Remote wakeup success.\r\n");
        } else {
        }
    }

#ifdef USE_LCD
    lcd_text_color_set(LCD_COLOR_RED);
    lcd_vertical_string_display(LCD_HINT_LINE0, 0, (uint8_t *)"---------------------------------------");
    lcd_text_color_set(LCD_COLOR_GREEN);
    lcd_vertical_string_display(LCD_HINT_LINE1, 0, (uint8_t *)"To start the HID class operations:  ");
    lcd_vertical_string_display(LCD_HINT_LINE2, 0, (uint8_t *)"Press User Key...             ");
#endif /* USE_LCD */

#endif /* USB_LOW_POWER */

    /*Key Tamper is in polling mode to detect user action */
    if(RESET == gd_eval_key_state_get(KEY_TAMPER)){
        usbh_usr_status = USBH_USER_RESP_OK;
    }

    return usbh_usr_status;
}
V2.0.0
usbh_user_status usbh_user_userinput(void)
{
    usbh_user_status usbh_usr_status = USR_IN_NO_RESP;

#if USB_LOW_POWER
    gd_eval_key_init(KEY_WAKEUP, KEY_MODE_EXTI);

    if(usb_host_hid.suspend_flag) {
        LCD_UsrLog("\n> Pls press Tamper key to make the USB host enter the suspended state.\n");
        LCD_UsrLog("\n> To wake up the USB host, pls press WAKEUP key (General wakeup).\n");

        if(usb_host_hid.dev_supp_remote_wkup) {
            LCD_UsrLog("> Or operate device (Remote wakeup).\n");
        }

        /* wait for Tamper key pressed */
        while(SET == gd_eval_key_state_get(KEY_TAMPER));
    } else {
        if(GENERAL_WAKEUP == usb_host_hid.wakeup_mode) {
            usb_host_hid.wakeup_mode = NORMAL_WORK;
            LCD_UsrLog("> General wakeup success.\r\n");
        } else if(REMOTE_WAKEUP == usb_host_hid.wakeup_mode) {
            usb_host_hid.wakeup_mode = NORMAL_WORK;
            LCD_UsrLog("> Remote wakeup success.\r\n");
        } else {
        }
    }

#ifdef USE_LCD
    lcd_text_color_set(LCD_COLOR_RED);
    lcd_vertical_string_display(LCD_HINT_LINE0, 0, (uint8_t *)"---------------------------------------");
    lcd_text_color_set(LCD_COLOR_GREEN);
    lcd_vertical_string_display(LCD_HINT_LINE1, 0, (uint8_t *)"To start the HID class operations:  ");
    lcd_vertical_string_display(LCD_HINT_LINE2, 0, (uint8_t *)"Press User Key...             ");
#endif /* USE_LCD */

#endif /* USB_LOW_POWER */

    /*Key Tamper is in polling mode to detect user action */
    if(RESET == gd_eval_key_state_get(KEY_TAMPER)){
        usbh_usr_status = USR_IN_RESP_OK;
    }

    return usbh_usr_status;
}

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/28_USB_Host/Host_HID/src/usbh_usr.c
fix reason:
bug fix
V1.2.0:
#include <string.h>
#include "usbh_usr.h"
#include "drv_usb_hw.h"
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bbb.h"
#include "ff.h"
V2.0.0
#include "usbh_usr.h"
#include "drv_usb_hw.h"
#include "usbh_msc_core.h"
#include "ff.h"

#include <string.h>

Fix file:
../GD32H73x_75x_Demo_Suites/GD32H759I_EVAL_Demo_Suites/Projects/28_USB_Host/Host_HID/src/usbh_usr.c
fix reason:
bug fix
V1.2.0:
        gd_eval_key_init(KEY_TAMPER, KEY_MODE_GPIO);
        gd_eval_key_init(KEY_WAKEUP, KEY_MODE_GPIO);
        gd_eval_key_init(KEY_USER, KEY_MODE_GPIO);

#endif /* USE_ULPI_PHY */
        gd_eval_key_init(KEY_TAMPER, KEY_MODE_GPIO);
        gd_eval_key_init(KEY_WAKEUP, KEY_MODE_GPIO);
none
__________________________________________________________________________________________________________________________

